﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.IO;


using AKMII.DMRA.Common;
using AKMII.DMRA.DataAccess;
using AKMII.DMRA.Business.Rule;

namespace AKMII.DMRA.DataLoader
{
    public class Downloader
    {
        private string userName = SystemConfiguration.CommonSetting.FtpUserName;
        private string password = SystemConfiguration.CommonSetting.FtpPassword;
        private string localDirec;

        public void Process(string source)
        {
            if (!string.IsNullOrEmpty(source))
            {
                if (source.EndsWith(@"\"))
                {
                    localDirec = source;

                    Config config = new Config();
                    if (config.FilesToBeDownload.Count > 0)
                    {
                        foreach (var file in Directory.GetFiles(source))
                        {
                            File.Delete(file);
                            Logger.Info("Delete history file at " + file);
                        }

                        this.Download(config.FilesToBeDownload);
                    }
                }
            }
        }

        #region Private Methods

        private List<string> Download(Dictionary<string, string> filesToBeDownload)
        {
            List<string> localFile = new List<string>();

            CommandHistoryAccessor accessor = new CommandHistoryAccessor();
            DateTime dateTime = accessor.GetLastExecuteTime(Command.Download.ToString());
            bool foundNewFileInFtp = false;
            foreach (string file in filesToBeDownload.Keys)
            {
                if (IsNeedDownload(file, dateTime))
                {
                    DateTime lastExecuteTime = DateTime.Now;
                    bool retry = false;
                    bool success = false;
                    foundNewFileInFtp = true;
                    do
                    {
                        string destPath = localDirec + filesToBeDownload[file];
                        success = TryDownload(file, destPath, ref retry);
                    } while (retry);
                    if (success)
                    {
                        localFile.Add(localDirec + filesToBeDownload[file]);
                        accessor.UpdateLastExecuteTime(Command.Download.ToString(), lastExecuteTime);
                    }
                }
            }
            if (foundNewFileInFtp)
            {
                Mail email = new Mail();
                email.Subject = Constants.MailSubjectFoundNewFile;
                email.Content = Constants.MailContentFoundNewFile;
                UserAccessor accesser = new UserAccessor();
                email.Recipients = accesser.GetMailAddress(UserType.Administrator);
                Utility.Send(email);
            }

            return localFile;
        }

        private bool IsNeedDownload(string url, DateTime dateTime)
        {
            if (GetFtpLastModified(url) > dateTime)
            {
                return true;
            }
            else
            {
                Logger.Info(string.Format("{0} is too old.", url));
                return false;
            }
        }

        private DateTime GetFtpLastModified(string url)
        {
            DateTime dt = DateTime.Now;
            bool retry = false;
            do
            {
                try
                {
                    dt = FtpUtils.GetTimestamp(url, this.userName, this.password);
                    retry = false;
                }
                catch (Exception e)
                {
                    if (retry)
                    {
                        retry = false;
                        Logger.Fatal(e.Message);
                        throw;
                    }
                    else
                    {
                        retry = true;
                        string err = e.Message;
                        Logger.Info("Try again due to: " + err);
                    }
                }
            } while (retry);
            return dt;
        }

        private bool TryDownload(string url, string destFilePath, ref bool retry)
        {
            bool result = false;
            try
            {
                FtpUtils.Download(url, this.userName, this.password, destFilePath);
                retry = false;
                result = true;
            }
            catch (System.ObjectDisposedException ode)
            {
                Logger.Info("Downloading done  with warning: " + ode.Message);
                retry = false;
                result = true;
            }
            catch (Exception e)
            {
                if (retry)
                {
                    retry = false;
                    string message = string.Format("TryDownload()\n{0}\n{1}\nException: {2}",
                        e.Message,
                        e.StackTrace,
                        Type.GetType(e.GetType().FullName));
                    Logger.Fatal(message);
                    Logger.Info(string.Format("failed to download, {0}", e.Message));
                }
                else
                {
                    Logger.Info("Info - try again");
                    retry = true;
                }
            }
            return result;
        }

        #endregion
    }
}
